package com.nku.mason.rpc.serviceside;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
/**
 * 1. 监听客户端TCP连接，接收到新的客户端请求后，将其封装成ExporterTask，由线程池执行
 * 2. 将客户端发送的二进制码流饭雪花成对象，反射调用服务实现者，获取执行结果。
 * 3. 将执行结果序列化，通过Socket发送给客户端。
 * 4. 远程服务调用完成后，释放Socket等连接资源，防止句柄泄露。
 * @author mason
 *
 */
public class RpcExporter {
	
	static Executor threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
	
	public static void exporter(String hostName, int port) throws Exception {
		ServerSocket server = new ServerSocket();
		server.bind(new InetSocketAddress(hostName, port));
		
		try {
			while(true) {
				threadPool.execute(new ExporterTask(server.accept()));
			}
		} finally {
			server.close();
		}
	}
	
	private static class ExporterTask implements Runnable {
		
		Socket client = null;
		public ExporterTask(Socket client) {
			this.client = client;
		}

		@Override
		public void run() {
			ObjectInputStream input = null;
			ObjectOutputStream output = null;
			try {
				input = new ObjectInputStream(client.getInputStream());
				String interfaceName = input.readUTF();
				Class<?> service = Class.forName(interfaceName);
				String methodName = input.readUTF();
				Class<?>[] parameterTypes = (Class<?>[]) input.readObject();
				Object[] arguments = (Object[]) input.readObject();
				Method method = service.getMethod(methodName, parameterTypes);
				Object result = method.invoke(service.newInstance(), arguments);
				output = new ObjectOutputStream(client.getOutputStream());
				output.writeObject(result);
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				if (output != null) {
					try {
						output.close();
					} catch (Exception e2) {
						e2.printStackTrace();
					}
				}
				
				if (input != null) {
					try {
						input.close();
					} catch (Exception e2) {
						e2.printStackTrace();
					}
				}
				
				if (client != null) {
					try {
						client.close();
					} catch (Exception e2) {
						e2.printStackTrace();
					}
				}
			}
		}
		
	}
}
